import * as bfun from '../../core/fbyte.js';
/**
 * 专门用于编码 (用树结构编码)
 * 仅支持 uint8array key
 */
//根节点 是0层
//每往下 加1层
const BNode = {
	newCreate(父, 层, b, code, pass) {
		let self = {
			pnd: 父,
			pass: 0, //经过权重
			level: 层 || 0,
			child: new Map(), //子节点
			code, //id		
			b
		};
		return self;
	},
	up(node, callback) {
		if (node) {
			callback(node)
			if (node.pnd) {
				BNode.up(node.pnd, callback);
			}
		}
	},
	//向下遍历公共函数
	down(node, callback) {
		if (node == null) return;
		let ta = this;
		//console.log(node)
		node.child.forEach(function(nd, b, map) {
			//vue 扩展对象的属性 extend 导致的问题
			if (nd == null) return;
			let flag = callback(node, nd, b);
			if (flag) return;
			ta.down(nd, callback);
		});
	},
	/**
	 * 插入固定长度的 bytes 改变树的结构
	 * @param {Object} node  树根节点 root 是第0层
	 * @param {Object} bytes  插入不限定长度的字节
	 * @param {Object} level  表示节点在第几level  从第一层开始
	 */
	setn(node, bytes, level) {
		let ta = this;
		//为空跳过	
		if (bytes == null || bytes.length == 0) return;
		level = level || 1;
		if (level > bytes.length) return;
		let b0 = bytes[level - 1];
		//console.log(b0)
		//如果节点为空创建一个
		let nd = node.child.get(b0);
		if (nd == null) {
			nd = ta.newCreate(node, level, b0);
			node.child.set(b0, nd);
		}
		//创建子节点
		nd.pass++;
		//继续下钻
		if (bytes.length > level) {
			level++;
			return ta.setn(nd, bytes, level);
		} else
			return nd;
	},
	put(pnd, nd) {
		pnd.child.set(nd.b, nd);
		nd.pnd = pnd;
	},
	/*
	插入不固定的长度
	如果树节点已经存在,挂在树节点下面,
	如果不存在,添加到父节点后面
	*/
	putNofixed(root, bytes) {
		let id = 1;
		let ta = this;

		function add(nd1, bs, level) {
			if (bs == null || bs.length == 0) return;
			level = level || 1;
			let b0 = bs[0];
			bs = bs.subarray(1);
			let nd2 = nd1.child.get(b0);
			if (nd2 == null) {
				nd2 = ta.newCreate(nd1, level, b0, id++);
				nd1.child.set(b0, nd2);
				add(root, bs, 0);
			} else {
				nd2.pass++;
				add(nd2, bs, ++level);
			}
		}
		add(root, bytes, 0);
	},

	//按照id大小排序
	sort_id(node) {
		let n = 0;

		function sort(node) {
			if (node == null) return;
			let ta = this;
			//console.log(node)
			if (node.child.size == 0) {
				node.code = ++n;
			} else {
				var arrayObj = Array.from(node.child);
				arrayObj.sort(function(a, b) {
					return a[0] - b[0]
				})
				node.child = new Map(arrayObj.map(i => [i[0], i[1]]));
				node.child.forEach(function(nd, b, map) {
					sort(nd);
				});
			}
		}
		sort(node);
		return n;
	},
	sort_kv(node) {
		let mp = new Map();
		let n = 0;
		let ta = this;

		function getBs(node) {
			let li = []
			ta.up(node, function(nd) {
				li.unshift(nd.b);
			});
			return li;
		}

		function sort(node) {
			if (node == null) return;
			let ta = this;
			//console.log(node)
			if (node.child.size == 0) {
				mp.set(++n, getBs(node));
			} else {
				var arrayObj = Array.from(node.child);
				arrayObj.sort(function(a, b) {
					return a[0] - b[0]
				})
				node.child = new Map(arrayObj.map(i => [i[0], i[1]]));
				node.child.forEach(function(nd, b, map) {
					sort(nd);
				});
			}
		}
		sort(node);
		return mp;
	},
	//以下两个方法 适用于map场合
	mount(父节点, 子节点) {
		if (父节点 == null || 子节点 == null) return null;
		子节点.pnd = 父节点;
		父节点.child.set(子节点.b, 子节点);
	},
	//从树指定节点开始 找到字节数据匹配的节点
	get(node, key) {
		let ta = this;
		if (node == null || key == null || key.length == 0) return node;
		if (node.child.size > 0) {
			let nd = node.child.get(key[0]);
			if (nd == null) return null;
			return ta.get(nd, key.subarray(1));
		}
	},
	//遍历输出节点
	view(root) {
		this.down(root, function(pnd, nd, key) {
			if (nd)
				console.log(pnd.b, '--', nd.b, nd.level, nd.code)
		});
	},
	//满层树,所有叶子都在最底层 , 其他层没有叶子
	//树的层必须大于1,否则直接输出树
	tree_ui8(root, 最大层) {
		let dict = []; //[元素,子节点个数]
		let ta = this;

		function add1(node) {
			let n = node.level;
			if (dict[n - 1] == null)
				dict[n - 1] = [];
			if (最大层 == n)
				dict[n - 1].push(node.b);
			else
				dict[n - 1].push([node.b, node.child.size]);
		}
		ta.down(root, function(pnd, nd, k) {
			if (nd.level > 0) {
				add1(nd);
			}
		});
		//console.log([head, dict]) ;		
		let n = 0;
		let arr = [最大层]; //不超过255 一个字节够了
		let maxlen = dict[最大层 - 1].length;
		arr.push(bfun.intToByte4(maxlen));
		arr.push(dict[最大层 - 1]);
		if (最大层 > 1) {
			for (let l = 最大层 - 2; l >= 0; l--) {
				//console.log(l, dict[l]);
				//遍历每层
				let ar = dict[l];
				arr.push(ar);
			};
		}
		return new Uint8Array(arr.flat(3));
	},
	ui8_tree(ui8) {
		let 最大层 = ui8[0];
		let 底长 = bfun.byte4ToInt(ui8, 1);
		let ta = this;
		let btnds = [];
		for (let i = 0; i < 底长; i++) {
			let nd = BNode.newCreate(null, 最大层, ui8[i + 5], 0);
			btnds.push(nd);
		};

		function mount(list, 层, nds) {
			
			while (list.length>0&&层>1){	
				层--;
				let narr1 = [];	
				let i=0;			
				let len=nds.length;
				while (nds.length>0) {
					//节点b,子节点个数
					let 子节点数 = list[i + 1];
					let nd = ta.newCreate(null, 层, list[i]);			
					for (let j = 0; j < 子节点数; j++) {
						let fe = nds.shift();
						BNode.mount(nd, fe);
					}
					narr1.push(nd);
					i+=2;
				}
				nds=narr1;			
				list=list.subarray(i);
			}
			return nds;			
		}
		let las = ui8.subarray(底长 + 5);
		if (最大层>1)
			btnds = mount(las, 最大层, btnds);

		let root = BNode.newCreate();
		while (btnds.length>0) {
			let fe = btnds.shift();
			BNode.put(root, fe);
		}
		return root;
	},

};


export default BNode;
